package com.zs.java.func;

import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author madison
 * @description
 * @date 2021/10/21 12:05
 */
public class LambdaTest {

    public static void main(String[] args) {
//        1.1 java8自带的常用函数式接口。
        Predicate<Integer> predicate = x -> x > 185;
        Student student = new Student("zs", 23, 175);
        System.out.println(
                "身高高于185吗？：" + predicate.test(student.getStature()));

        Consumer<String> consumer = System.out::println;
        consumer.accept("命运由我不由天");

        Function<Student, String> function = Student::getName;
        String name = function.apply(student);
        System.out.println(name);

        UnaryOperator<Boolean> unaryOperator = uglily -> !uglily;
        Boolean apply = unaryOperator.apply(true);
        System.out.println(apply);

        BinaryOperator<Integer> operator = (x, y) -> x * y;
        Integer integer = operator.apply(2, 3);
        System.out.println(integer);

        test(() -> "我是一个演示的函数式接口");

//        2.1 collect(Collectors.toList())
        List<Student> studentList = Stream.of(new Student("路飞", 22, 175),
                new Student("红发", 40, 180),
                new Student("白胡子", 50, 185)
        ).collect(Collectors.toList());
        System.out.println(studentList);

//        2.2 filter
        List<Student> students = new ArrayList<>(3);
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));

        List<Student> list = students.stream()
                .filter(stu -> stu.getStature() < 180)
                .collect(Collectors.toList());
        System.out.println(list);

//        2.3 map
        List<String> names = students.stream().map(stu -> stu.getName())
                .collect(Collectors.toList());
        System.out.println(names);

//        2.4 flatMap
        List<Student> studentList1 = Stream.of(students,
                        Arrays.asList(new Student("艾斯", 25, 183),
                                new Student("雷利", 48, 176)))
                .flatMap(stu -> stu.stream()).collect(Collectors.toList());
        System.out.println(studentList1);

//        2.5 max和min
        Optional<Student> max = students.stream()
                .max(Comparator.comparing(stu -> stu.getAge()));
        Optional<Student> min = students.stream()
                .min(Comparator.comparing(stu -> stu.getAge()));
        //判断是否有值
        if (max.isPresent()) {
            System.out.println(max.get());
        }
        if (min.isPresent()) {
            System.out.println(min.get());
        }

//        2.6 count
        long count = students.stream().filter(s1 -> s1.getAge() < 45).count();
        System.out.println("年龄小于45岁的人数是：" + count);

//        2.7 reduce
        Integer reduce = Stream.of(1, 2, 3, 4).reduce(0, (acc, x) -> acc + x);
        System.out.println(reduce);

        /***************** 三、高级集合类及收集器 ****************/
//        3.1 转换成值
        List<Student> students1 = new ArrayList<>(3);
        students1.add(new Student("路飞", 23, 175));
        students1.add(new Student("红发", 40, 180));
        students1.add(new Student("白胡子", 50, 185));

        OutstandingClass ostClass1 = new OutstandingClass("一班", students1);
        //复制students1，并移除一个学生
        List<Student> students2 = new ArrayList<>(students1);
        students2.remove(1);
        OutstandingClass ostClass2 = new OutstandingClass("二班", students2);
        //将ostClass1、ostClass2转换为Stream
        Stream<OutstandingClass> classStream = Stream.of(ostClass1, ostClass2);
        OutstandingClass outstandingClass = biggestGroup(classStream);
        System.out.println("人数最多的班级是：" + outstandingClass.getName());

        System.out.println("一班平均年龄是：" + averageNumberOfStudent(students1));

//        3.2 转换成块
        Map<Boolean, List<Student>> listMap = students.stream().collect(
                Collectors.partitioningBy(stu -> stu.getSpecialities().
                        contains(SpecialityEnum.SING)));
        System.out.println(listMap);

        // 3.3 数据分组
        Map<SpecialityEnum, List<Student>> listMap1 =
                students.stream().collect(
                        Collectors.groupingBy(stu -> stu.getSpecialities().get(0)));
//        3.4 字符串拼接
        String strNames = students.stream()
                .map(Student::getName).collect(Collectors.joining(",", "[", "]"));
        System.out.println(strNames);
    }

    /**
     * 获取人数最多的班级
     */
    private static OutstandingClass biggestGroup(Stream<OutstandingClass> outstandingClasses) {
        return outstandingClasses.collect(Collectors.maxBy(Comparator.comparing(ostClass -> ostClass.getStudents().size())))
                .orElseGet(OutstandingClass::new);
    }


    /**
     * 计算平均年龄
     */
    private static double averageNumberOfStudent(List<Student> students) {
        return students.stream().collect(Collectors.averagingInt(Student::getAge));
    }

    public static void test(Worker worker) {
        String work = worker.work();
        System.out.println(work);
    }

    public interface Worker {
        String work();
    }

    private static class Student {
        private String name;
        private int age;
        private int stature;
        private List<SpecialityEnum> specialities;

        public Student(String name, int age, int stature) {
            this.name = name;
            this.age = age;
            this.stature = stature;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public int getStature() {
            return stature;
        }

        public void setStature(int stature) {
            this.stature = stature;
        }

        public List<SpecialityEnum> getSpecialities() {
            return specialities;
        }

        public void setSpecialities(List<SpecialityEnum> specialities) {
            this.specialities = specialities;
        }

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", stature=" + stature +
                    '}';
        }
    }

    private enum SpecialityEnum {
        SING,
        DANCE,
        SWIMMING,
        RUNNING
    }

    private static class OutstandingClass {
        private String name;
        private List<Student> students;

        public OutstandingClass(String name, List<Student> students) {
            this.name = name;
            this.students = students;
        }

        public OutstandingClass() {

        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public List<Student> getStudents() {
            return students;
        }

        public void setStudents(List<Student> students) {
            this.students = students;
        }
    }
}
